from django.shortcuts import render

# 导入Response包
from rest_framework.response import Response

# 导入APIView包
from rest_framework.views import APIView

# 解析jwt_token的模块
from rest_framework_jwt.utils import jwt_decode_handler
# 时间模块
import datetime
# 导入请求莫酷似
import requests

# 导入随机包
import random
import time
# 导入序列化器
from miaoapp.miaoser import *


# 温度查询
class RequestTemp(APIView):
    def get(self, request):
        # 获取运单id
        oid = request.GET.get('oid', None)
        # 查询运单信息
        order = Order.objects.get(id=int(oid))
        # 根据运单id查询温度表信息
        temp = Temperature.objects.filter(order_id=int(oid))
        # 序列化温度表数据
        templist = TemperatureSer(temp, many=True).data
        # 遍历
        for i in templist:
            # 将温度表中的运单id转换成运单号
            i['oid'] = order.ordername
        return Response({'code': 200, 'templist': templist})


# 订单回传
class AccOrder(APIView):
    def get(self, request):
        # 获取查询参数
        send_add = request.GET.get('send_add[]')
        take_add = request.GET.get('take_add[]')
        start_time = request.GET.get('start_time')
        end_time = request.GET.get('end_time')
        # 如果开始时间小于结束时间
        if start_time > end_time:
            # 时间调换位置
            start_time, end_time = end_time, start_time
        # 获取发货地址
        send_add = SendAddress.objects.get(id=int(send_add))
        # 将发货地址编码改为发货地址名
        send_add = send_add.start_add
        # 获取收货地址
        take_add = TakeAddress.objects.filter(take_code=str(take_add)).first()
        # 将收货地址编码改为收货地址名
        take_add = take_add.end_add
        # 转换成时间格式
        start_time = datetime.datetime.strptime(start_time, "%Y-%m-%dT%H:%M:%S.%fZ")
        end_time = datetime.datetime.strptime(end_time, "%Y-%m-%dT%H:%M:%S.%fZ")
        # 转换成日期格式
        start_time = datetime.datetime.date(start_time)
        end_time = datetime.datetime.date(end_time)
        # ➕一天
        day = datetime.timedelta(days=+1)
        # 获取到的日期全部加一天
        start_time = start_time + day
        end_time = end_time + day
        print(send_add)
        print(take_add)
        send_take = Order.objects.filter(start_add=send_add, end_add=take_add).first()
        print(send_take)
        send_lng = send_take.send_add.split(',')[0]
        send_lat = send_take.send_add.split(',')[1]
        take_lng = send_take.take_add.split(',')[0]
        take_lat = send_take.take_add.split(',')[1]
        # 按条件查询有运单
        order = Order.objects.filter(start_add=send_add, end_add=take_add, start_time__range=[start_time, end_time])
        # 返回运单信息
        orderlist = OrderSer(order, many=True).data
        orderinfo = order_status(orderlist)
        return Response(
            {'code': 200, 'orderinfo': orderinfo, 'send_lng': send_lng, 'send_lat': send_lat, 'take_lng': take_lng,
             'take_lat': take_lat})


# 收货地址回传
class AddTakeOrder(APIView):
    def get(self, request):
        send_addcode = request.GET.get('send_add[]', None)
        take_add = TakeAddress.objects.filter(send_code=str(send_addcode))
        take_addlist = TakeAddressSer(take_add, many=True).data
        sancenglist = []
        ercenglist = []
        takelist = []

        for i in take_addlist:
            sancengdict = {}
            ercengdict = {}
            yicengdict = {}
            sancengdict['value'], sancengdict['label'] = i['take_code'], i['end_add']
            sancenglist.append(sancengdict)
            erceng = TakeAddress.objects.filter(take_code=str(i['end_code'])).first()
            ercengdict['value'], ercengdict['label'] = erceng.take_code, erceng.end_add
            ercengdict['children'] = sancenglist
            ercenglist.append(ercengdict)
            yiceng = TakeAddress.objects.filter(take_code=str(erceng.end_code)).first()
            yicengdict['value'],yicengdict['label'] = yiceng.take_code,yiceng.end_add
            yicengdict['children'] = ercenglist
            takelist.append(yicengdict)
        # print(takelist)
        return Response({'code': 200, 'message': '获取成功', 'takeaddlist': takelist})


# 根据地址查询订单
class AddSearchOrder(APIView):
    def get(self, request):
        # 获取所有发货地址
        send_add = SendAddress.objects.all()
        # 序列化发货地址
        sendlist = SendAddressSer(send_add, many=True).data
        addlist = []
        # 遍历序列化后的发货地址
        for i in sendlist:
            waidict = {}
            # 如果当前字段start_code为空时
            if not i['start_code']:
                # 将需要的地址编码及地址信息添加到顶级字典中
                waidict['value'], waidict['label'] = i['id'], i['start_add']
                # 添加到列表中
                addlist.append(waidict)
        # 遍历顶级字典列表
        for i in addlist:
            # 查询发货地址表中start_code等于顶级字典中value的数据
            send = SendAddress.objects.filter(start_code=str(i['value']))
            # 序列化查询到的数据
            slist = SendAddressSer(send, many=True).data
            # 遍历序列化数据
            for j in slist:
                neidict = {}
                # 如果字典中value等于序列化中start_code
                if str(i['value']) == j['start_code']:
                    # 则作为二级菜单选项，添加到二级字典中
                    neidict['value'], neidict['label'] = j['id'], j['start_add']
                    # 为后面有二级菜单的顶级字典添加一个新的二级菜单列表
                    i['children'] = []
                    # 将二级菜单添加到该列表中
                    i['children'].append(neidict)
                    # 再次查询发货地址表中start_code等于二级菜单中value的数据
                    sanji = SendAddress.objects.filter(start_code=str(neidict['value']))
                    # 序列化此部分数据
                    sanlist = SendAddressSer(sanji, many=True).data
                    # 编列序列化后的数据
                    for z in sanlist:
                        sandict = {}
                        # 如果序列化之后的start_code数据中，有等于二级序列化数据中的id
                        if str(z['start_code']) == str(j['id']):
                            # 则将此部分数据作为三级菜单地址
                            sandict['value'], sandict['label'] = z['id'], z['start_add']
                            # 为有数据的二级菜单创建一个空的列表，以便于存储三级菜单地址
                            neidict['children'] = []
                            # 将三级菜单内容添加到此列表中
                            neidict['children'].append(sandict)
        # 将处理好的发货地址数据，传给前端展示
        return Response({'code': 200, "message": '获取成功', 'sendaddlist': addlist})


# 返回该订单收发货的经纬度
class OrderAddress(APIView):
    def get(self, request):
        # 获取运单id
        oid = request.GET.get('0', None)
        # 查询运单
        order = Order.objects.get(id=int(oid))
        # 使用filter查询运单详情，避免调用下面函数添加所属数据时报错
        orderinfo = Order.objects.filter(id=int(oid))
        # 序列化查询数据
        orderinfo = OrderSer(orderinfo, many=True).data
        # 调用函数，添加所需数据
        orderlist = order_status(orderinfo)
        # 经纬度切片，分出lng，lat
        send_add = order.send_add.split(',')
        take_add = order.take_add.split(',')
        send_lng, send_lat = send_add[0], send_add[1]
        take_lng, take_lat = take_add[0], take_add[1]
        return Response(
            {'code': 200, 'orderlist': orderlist, 'send_lng': send_lng, 'send_lat': send_lat, 'take_lng': take_lng,
             'take_lat': take_lat})


# 统计所调用函数
def Pagination(activeName, data_start, data_end, today, tom):
    # 获取全部订单
    if activeName == '全部':
        # 查询条件：__gt:状态大于0，为在途，完成，__range:在范围内
        order = Order.objects.filter(cond__gt=0, start_time__range=[tom, today])[data_start:data_end]
        orderlist = OrderSer(order, many=True).data
    elif activeName == '在途':
        order = Order.objects.filter(cond=1, start_time__range=[tom, today])[data_start:data_end]
        orderlist = OrderSer(order, many=True).data
    elif activeName == '完成':
        order = Order.objects.filter(cond=2, start_time__range=[tom, today])[data_start:data_end]
        orderlist = OrderSer(order, many=True).data
    else:
        order = Order.objects.filter(temp_log='报警', start_time__range=[tom, today])[data_start:data_end]
        orderlist = OrderSer(order, many=True).data
    order_status(orderlist)
    return orderlist


# 统计
class TotalOrder(APIView):
    def get(self, request):
        activeName = request.GET.get('activeName', None)
        OrderName = request.GET.get('OrderName', None)
        page = request.GET.get('page', None)
        size = request.GET.get('size', None)
        data_start = (int(page) - 1) * int(size)
        data_end = int(page) * int(size)
        # 获取当前日期
        today = datetime.datetime.date(datetime.datetime.now())
        # 当前日期➕1天
        dayone = datetime.timedelta(days=+1)
        today = today + dayone
        if activeName == '当天':
            dayone = datetime.timedelta(days=-1)
            # 计算出明天日期
            tom = today + dayone
            # 在途+已完成运单数
            total = Order.objects.filter(cond__gt=0, start_time__range=[tom, today]).count()
            # 在途运单
            cond = Order.objects.filter(cond=1, start_time__range=[tom, today]).count()
            # 报警运单
            temp_log = Order.objects.filter(temp_log='报警', start_time__range=[tom, today]).count()
            pagein = Pagination(OrderName, data_start, data_end, today, tom)
            return Response(
                {'code': 200, 'total': total, 'cond': cond, 'temp_log': temp_log, 'orderlist': pagein}
            )
        elif activeName == '7天':
            # 当前日期-7天
            qitian = datetime.timedelta(days=-7)
            # 计算出明天日期
            tom = today + qitian
            # 在途+已完成运单数
            total = Order.objects.filter(cond__gt=0, start_time__range=[tom, today]).count()
            # 在途运单
            cond = Order.objects.filter(cond=1, start_time__range=[tom, today]).count()
            # 报警运单
            temp_log = Order.objects.filter(temp_log='报警').count()
            pagein = Pagination(OrderName, data_start, data_end, today, tom)

            return Response(
                {'code': 200, 'total': total, 'cond': cond, 'temp_log': temp_log, 'orderlist': pagein}
            )
        else:
            # 当前日期-30天
            sanshitian = datetime.timedelta(days=-30)
            # 计算出明天日期
            tom = today + sanshitian
            # 在途+已完成运单数
            total = Order.objects.filter(cond__gt=0, start_time__range=[tom, today]).count()
            # 在途运单
            cond = Order.objects.filter(cond=1, start_time__range=[tom, today]).count()
            # 报警运单
            temp_log = Order.objects.filter(temp_log='报警').count()
            pagein = Pagination(OrderName, data_start, data_end, today, tom)
            return Response(
                {'code': 200, 'total': total, 'cond': cond, 'temp_log': temp_log, 'orderlist': pagein}
            )


# 判断温度是否报警
def IfTemp(order_data):
    # 获取运单id
    oid = order_data['id']
    # 获取标签名
    tagname = order_data['tag_id']
    # 获取运单信息
    order = Order.objects.get(id=int(oid))
    # 查询该运单的所有温度
    temp = Temperature.objects.filter(order_id=int(oid))
    # 获取标签信息
    tag = Tag.objects.filter(tag_id=tagname).first()
    # 获取货物类型信息
    fix = Fixing.objects.get(id=int(tag.fix_id))
    recore_time = fix.ent_time
    count = Temperature.objects.filter(order_id=int(oid)).count() / int(recore_time)
    # 获取报警类型
    warn = Warn.objects.filter(fix_id=int(fix.id))
    # 序列化报警类型
    warnlist = WarnSer(warn, many=True).data
    for i in warnlist:
        if not i['min_temp']:
            tempcount = Temperature.objects.filter(tempera__gt=i['max_temp']).count()
            if tempcount > count:
                # 是，则报警
                order.temp_log = '报警'
                order.save()
        elif not i['max_temp']:
            tempcount = Temperature.objects.filter(tempera__lt=i['min_temp']).count()
            if tempcount > count:
                # 是，则报警
                order.temp_log = '报警'
                order.save()
        else:
            tempcount = Temperature.objects.filter(tempera__gt=i['max_temp'], tempera__lt=i['min_temp']).count()
            if tempcount > count:
                # 是，则报警
                order.temp_log = '报警'
                order.save()
    return order_data


# 收货
class TakeOrder(APIView):
    def put(self, request):
        # 获取收货运单的id
        order_data = request.data.get('data', None)
        # 查询数据库
        order = Order.objects.get(id=int(order_data['id']))
        # 修改状态级结束时间
        order.cond = 2
        order.end_time = datetime.datetime.now()
        # 保存
        order.save()
        # 收货同时将温度存入温度表中
        writetemp(order.id)
        # 收货同时查询温度是否报警
        IfTemp(order_data)
        return Response({'code': 200, 'message': '收货成功'})


# 运单发货，开始记录温度
def writetemp(oid):
    # 方法一
    # 遍历10次
    date_time = datetime.datetime.now()
    for i in range(20):
        # 遍历小数
        num = random.uniform(10, 20)
        # 只取小数的两位值
        temp = ('%.2f') % num
        date_time += datetime.timedelta(minutes=5)
        # 存入温度表
        Temperature.objects.create(order_id=int(oid), tempera=temp, create_time=date_time)
    return oid


# 将所需信息添加到运单数据类型中
def order_status(orderlist):
    for i in orderlist:
        # 获取标签id
        tagid = i['tag_id']
        # 获取标签信息
        tag = Tag.objects.get(id=int(tagid))
        # 获取货物信息
        fix = Fixing.objects.get(id=int(tag.fix_id))
        # 将所需数据添加到字典中
        i['tag_id'] = tag.tag_id
        i['name'] = fix.name
        i['desc'] = fix.desc
        i['min_temp'] = fix.min_temp
        i['max_temp'] = fix.max_temp
        i['scope_temp'] = fix.min_temp + '~' + fix.max_temp
        i['ent_time'] = fix.ent_time
        i['delay_time'] = fix.delay_time
    return orderlist


# 已使用的运单信息
class OrderStatus(APIView):
    def get(self, request):
        # 获取查询的类别
        name = request.GET.get('OrderName', None)
        # 获取页码
        page = request.GET.get('page', None)
        # 获取一页显示多少条数据
        size = request.GET.get('size', None)
        # 从哪开始切
        data_start = (int(page) - 1) * int(size)
        # 切到哪
        data_end = int(page) * int(size)
        # 查询类型为全部
        if name == "全部":
            # 查询出不是待使用的运单
            order = Order.objects.filter(cond__gt=0).order_by("-start_time")[data_start:data_end]
            # 总条数
            total = Order.objects.filter(cond__gt=0).count()
            # 序列化
            orderlist = OrderSer(order, many=True).data
            order_status(orderlist)
        # 查询类型为在途
        elif name == "在途":
            # 查询在途中的运单
            order = Order.objects.filter(cond=1).order_by("-start_time")[data_start:data_end]
            # 总条数
            total = Order.objects.filter(cond=1).count()
            # 序列化
            orderlist = OrderSer(order, many=True).data
            order_status(orderlist)
        # 查询类型为完成
        elif name == "完成":
            # 查询已完成的运单
            order = Order.objects.filter(cond=2).order_by("-start_time")[data_start:data_end]
            # 总条数
            total = Order.objects.filter(cond=2).count()
            # 序列化
            orderlist = OrderSer(order, many=True).data
            order_status(orderlist)
        # 其余归属为报警类型
        else:
            # 查询报警的运单
            order = Order.objects.filter(temp_log=name).order_by("-start_time")[data_start:data_end]
            # 总条数
            total = Order.objects.filter(temp_log=name).count()
            # 序列化
            orderlist = OrderSer(order, many=True).data
            order_status(orderlist)
        return Response({'code': 200, 'orderlist': orderlist, 'total': total})


# 运单信息所调函数
def order_list(orderlist):
    for i in orderlist:
        cust = Customer.objects.get(id=int(i['cust_uid']))
        custser = CustomerSer(cust).data
        # 将客户信息添加到展示列表中
        i['cname'] = custser['cname']
        i['address'] = custser['address']
        i['uname'] = custser['uname']
        i['phone'] = custser['phone']
    return orderlist


# 未使用的运单信息
class OrderInfo(APIView):
    def get(self, request):
        # 页码
        page = request.GET.get('page', None)
        if not page:
            orderID = request.GET.get('0', None)
            order = Order.objects.filter(id=int(orderID), cond=0)
            total = Order.objects.filter(id=int(orderID), cond=0).count()
            orderlist = OrderSer(order, many=True).data
            order_list(orderlist)
        else:
            # 一页多少条
            size = request.GET.get('size', None)
            # 定义从哪开始切
            data_start = (int(page) - 1) * int(size)
            # 切到哪
            data_end = int(page) * int(size)
            # 获取所有运单信息传递给前端展示
            order = Order.objects.all().order_by("cond")[data_start:data_end]
            total = Order.objects.all().count()
            orderlist = OrderSer(order, many=True).data
            order_list(orderlist)
        return Response({'code': 200, 'orderlist': orderlist, 'total': total})

    # 添加运单
    def post(self, request):
        data = request.data
        Order.objects.create(ordername=data['order'], cust_uid=data['customer'])
        return Response({'code': 200, 'message': '添加成功'})

    # 发货-修改运单状态：在途中
    def put(self, request):
        # 获取发货的运单号级使用的标签id
        data = request.data
        order = Order.objects.get(id=data['id'])
        order = AddWrite(data, order)
        # 将标签写入的运单表中
        order.tag_id = data['taglist']
        # 运单状态修改为在途中
        order.cond = 1
        order.start_time = datetime.datetime.now()
        order.save()
        # 遍历标签id
        tag = Tag.objects.get(id=int(data['taglist']))
        # 修改标签状态为已使用
        tag.status = 1
        tag.update_time = datetime.datetime.now()
        tag.save()
        return Response({'code': 200, 'message': '发货成功'})


# 收发货地址存储
def AddWrite(data, order):
    '''将发货地址信息存入发货地址表中'''
    # 定义一个变量，来接收发货地址的县级code码
    send_code = ''
    # 发货地址
    send_add = geocode(data['send_add'])
    # 将发货地址经纬度写入到order表中
    order.send_add = send_add[0]
    # 获取省份信息
    province = send_add[2]
    # 获取市级信息
    qu = send_add[3]
    # 获取区或县级信息
    district = send_add[4]
    # 如果县级不存在，则将市级存入运单表中
    if not district:
        # 将发货地址写入到order表中
        order.start_add = send_add[3]
    order.start_add = send_add[4]
    # 解析省份信息，获取编码
    prov = geocode(province)
    # pcode为省份编码
    pcode = prov[1]
    # 查看表中是否已存在此省份
    send_prov = SendAddress.objects.filter(id=int(pcode)).first()
    # 如果不存在
    if not send_prov:
        # 将省份信息写入发货数据表中
        SendAddress.objects.create(id=pcode, start_add=province)
    # 如果省级与市级不相同时
    if qu != province:
        # 解析市级信息
        q = geocode(qu)
        # qcode为市级编码
        qcode = q[1]
        # 查看表中是否存在此市级
        send_qu = SendAddress.objects.filter(id=int(qcode)).first()
        # 不存在，写入表中
        if not send_qu:
            SendAddress.objects.create(id=qcode, start_code=pcode, start_add=qu)
        if district:
            # 解析县级信息
            dis = geocode(district)
            dcode = dis[1]
            # 查询表中是否存在此县级
            send_dis = SendAddress.objects.filter(id=int(dcode)).first()
            # 不存在，写入表中
            if not send_dis:
                SendAddress.objects.create(id=dcode, start_code=qcode, start_add=district)
                send_code = dcode
            else:
                send_code = send_dis.id
    else:
        # 解析县级信息
        dis = geocode(district)
        dcode = dis[1]
        # 查询县级信息是否存在表中
        send_dis = SendAddress.objects.filter(id=int(dcode)).first()
        # 不存在，写入表中
        if not send_dis:
            SendAddress.objects.create(id=dcode, start_code=pcode, start_add=district)
            send_code = dcode
        else:
            send_code = send_dis.id
    '''将收货地址信息存入发货地址表中'''
    # 收货地址
    take_add = geocode(data['take_add'])
    order.take_add = take_add[0]
    # 获取省份信息
    province = take_add[2]
    # 获取市级信息
    qu = take_add[3]
    # 获取区或县级信息
    district = take_add[4]
    # 如果县级不存在，则把市级存入运单表中
    if not district:
        order.end_add = take_add[3]
    order.end_add = take_add[4]
    # 解析省份信息，获取编码
    prov = geocode(province)
    # pcode为省份编码
    pcode = prov[1]
    # 查看表中是否已存在此省份
    send_prov = TakeAddress.objects.filter(take_code=int(pcode)).first()
    # 如果不存在
    if not send_prov:
        # 将省份信息写入发货数据表中
        TakeAddress.objects.create(take_code=pcode, end_add=province)
    # 如果省级与市级不相同时
    if qu != province:
        # 解析市级信息
        q = geocode(qu)
        # qcode为市级编码
        qcode = q[1]
        take = TakeAddress.objects.filter(take_code=qcode)
        if not take:
            TakeAddress.objects.create(take_code=qcode, end_code=pcode, end_add=qu)
        if district:
            # 解析县级信息
            dis = geocode(district)
            dcode = dis[1]
            take = TakeAddress.objects.filter(send_code=send_code, take_code=dcode)
            if not take:
                TakeAddress.objects.create(take_code=dcode, send_code=send_code, end_code=qcode, end_add=district)
    else:
        # 解析县级信息
        dis = geocode(district)
        dcode = dis[1]
        take = TakeAddress.objects.filter(send_code=send_code, take_code=dcode)
        if not take:
            TakeAddress.objects.create(take_code=dcode, send_code=send_code, end_code=pcode, end_add=district)
    return order


# 将地址转换成经纬度
def geocode(address):
    parameters = {'address': address, 'key': '6c5370a0433a13dcdf6179300fa5841e'}
    base = 'http://restapi.amap.com/v3/geocode/geo'
    response = requests.get(base, parameters)
    answer = response.json()
    if answer['count'] == '0':
        return "error", "", "", ""
    # 解析出经纬度
    location = answer['geocodes'][0]['location']
    # 解析出城市编码
    adcode = answer['geocodes'][0]['adcode']
    # 声
    province = answer['geocodes'][0]['province']
    # 市/区
    qu = answer['geocodes'][0]['city']
    # 县/县级市
    district = answer['geocodes'][0]['district']
    return location, adcode, province, qu, district


# 客户视图
class CustomerInfo(APIView):
    def get(self, request):
        # 获取页码
        page = request.GET.get('page', None)
        if not page:
            cust = Customer.objects.all()
            # 序列化数据
            custlist = CustomerSer(cust, many=True).data
            return Response({'code': 200, 'custlist': custlist})
        else:
            # 获取一页多少条
            size = request.GET.get('size', None)
            # 从哪开始切
            data_start = (int(page) - 1) * int(size)
            # 切到哪
            data_end = int(page) * int(size)
            # 获取全部客户信息
            cust = Customer.objects.all()[data_start:data_end]
            # 序列化数据
            custlist = CustomerSer(cust, many=True).data
            # 获取客户总个数
            total = Customer.objects.all().count()
            return Response({'code': 200, 'custlist': custlist, 'total': total})

    # 添加客户
    def post(self, request):
        data = request.data
        Customer.objects.create(cname=data['cname'], address=data['address'], uname=data['uname'], phone=data['phone'])
        return Response({'code': 200, 'message': '添加成功'})


# 生成随机货物类型名
class OrderName(APIView):
    def get(self, request):
        # 随机生成一个订单
        order = str(datetime.datetime.now().strftime("%Y%m%d%H%M%S") + str(random.randint(10, 99)))
        return Response({'code': 200, 'message': '生成成功', 'order': order})
